package lumis.portal.channel;

import static lumis.portal.PortalRequestParameters.PAGE_PARAMETER_CHANNELID;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import lumis.portal.PortalException;
import lumis.portal.PortalObjectNotFoundException;
import lumis.portal.authentication.SessionConfig;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.manager.ManagerFactoryInternal;
import lumis.portal.page.PageConfig;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.portal.url.WebResource;
import lumis.portal.url.IURLManager.CreateStrategy;

/**
 * A web resource that corresponds to a link that is directly to a channel.
 *
 * @version $Revision: 12710 $ $Date: 2011-03-18 17:00:16 -0300 (Fri, 18 Mar 2011) $
 * @since 5.0.0
 */
@Entity
@DiscriminatorValue("C")
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ChannelWebResource extends WebResource
{
	private String channelId;

	/**
	 * Creates a new ChannelWebResource.
	 * <p>
	 * ChannelWebResource may not be publicly created, so its constructor has
	 * package visibility.
	 * 
	 * @since 5.0.0
	 */
	ChannelWebResource()
	{
	}
	
	// -- Methods from WebResource -- //
	
	@Override
	public String getName()
	{
		return localize(getChannel().getName());
	}

	@Override
	public String getTitle()
	{
		return getName();
	}
	
	@Override
	public WebResource getParent()
	{
		try
		{
			String parentId = getChannel().getParentId();
			if (parentId != null)
			{
				return ManagerFactoryInternal.getURLManager().getWebResourceByDynamicPath(
						"/main.jsp?" + PAGE_PARAMETER_CHANNELID + "=" + parentId,
						CreateStrategy.AUTO, getLocale());
			}
			else
			{
				return null;
			}
		}
		catch (PortalException e)
		{
			throw new RuntimeException(e);
		}
	}

	@Override
	public Map<String, String[]> getParameterMap()
	{
		return Collections.emptyMap();
	}

	@Override
	public Map<String, List<String>> getProperties()
	{
		try
		{
			return ManagerFactory.getPropertyBagManager().get(getChannel().getPropertyBagId()).getValueMap();
		}
		catch (PortalException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	@Override
	protected String getPath(boolean considerGuestOnlyCache)
	{
		// channel web resource gives priority to friendly URL as its path
		if (isFriendlyURLEnabled())
			return getFriendlyPath() + "/";
		
		// if no friendly URL, but has cache enabled, use the path for the cache
		if (isCacheEnabled(considerGuestOnlyCache))
			return getPageCache().getFilePath();
		
		// otherwise use the dynamic path
		return getDynamicPath();
	}
	
	@Override
	public boolean isCacheEnabled(boolean considerGuestOnlyCache)
	{
		if (!super.isCacheEnabled(considerGuestOnlyCache))
			return false;
		
		// check if cache configuration in the default page is of appropriated type
		try
		{
			if (considerGuestOnlyCache)
			{
				return true;
			}
			else
			{
				try
				{
					// get channel's default page
					PageConfig page = ManagerFactory.getPageManager().getFirstPageByChannelIdRecursively(
							SessionConfig.getCurrentSessionConfig(), getChannelId(), 
							PortalTransactionFactory.getCurrentTransaction());
					
					// check page cache type
					int pageCacheType = ManagerFactory.getPageManager().getCachePage(SessionConfig.getCurrentSessionConfig(), 
							page, PortalTransactionFactory.getCurrentTransaction());
					return pageCacheType == PageConfig.PAGE_CACHE_TYPE_ALL_USERS;
				}
				catch (PortalObjectNotFoundException e)
				{
					// if the channel has no page, assume its cache is disabled
					return false;
				}
			}
		}
		catch (PortalException e)
		{
			throw new RuntimeException(e);
		}
	}

	@Override
	protected boolean isFriendlyURLEnabled()
	{
		return super.isFriendlyURLEnabled();
	}

	@Override
	public String getFriendlyURLPattern()
	{
		String pattern;
		ChannelConfig channel = getChannel();
		if (channel.isFriendlyURLPatternEnabled())
		{
			// get pattern from channel definition
			pattern = channel.getFriendlyURLPattern();
			if (pattern == null)
				pattern = "";
		}
		else
		{
			pattern = super.getFriendlyURLPattern();
		}
		
		return pattern;
	}
	
	@Override
	protected boolean hasSSI()
	{
		try
		{
			// get channel's default page
			PageConfig page = ManagerFactory.getPageManager().getFirstPageByChannelIdRecursively(
					SessionConfig.getCurrentSessionConfig(), getChannelId(), 
					PortalTransactionFactory.getCurrentTransaction());
			return page.getServerSideIncludeType() == PageConfig.PAGE_SERVER_SIDE_INCLUDE_YES;
		}
		catch (PortalObjectNotFoundException e)
		{
			// if the channel has no page, assume it has no SSI
			return false;
		}
		catch (PortalException e)
		{
			throw new RuntimeException(e);
		}
	}
	
	@Override
	protected String getRecommendedFileExtension()
	{
		return super.getRecommendedFileExtension();
	}
	
	// -- Specific ChannelWebResource methods -- //
	
	/**
	 * Returns the channel this web resource represents.
	 * @return the channel.
	 * @since 5.0.0
	 */
	private ChannelConfig getChannel()
	{
		try
		{
			return ManagerFactory.getChannelManager().get(SessionConfig.getCurrentSessionConfig(), channelId, PortalTransactionFactory.getCurrentTransaction());
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * Returns the identifier of the channel this web resource represents.
	 * @return the channel identifier.
	 * @since 5.0.0
	 */
	public String getChannelId()
	{
		return this.channelId;
	}

	/**
	 * Sets the identifier of the channel this web resource represents.
	 * @param channelId the channel identifier.
	 * @since 5.0.0
	 */
	void setChannelId(String channelId)
	{
		this.channelId = channelId;
	}
}
